# -*- coding: utf-8 -*-

# @Project : UI_KDTFrameWork
# @Author  : Mr.Deng
# @Time    : 2021/9/25 22:42

from tools.parseExcel import ParseExcel, Variable
from tools.keywordMapApi import key_word_map_api
from tools.logConfig import Logger
from tools.threadExecute import run_by_thread
from tools.resultStatistics import result_statistics

from config.filePathConfig import *
from actions import Base

import traceback
import os

Log = Logger().origin_logger


def get_run_case_file_list(caseFileName=None):
    """
    获取测试用例文件列表
    :param caseFileName: 文件名称
    :return:
    """
    # 不指定测试文件，默认就全部执行
    if caseFileName is None:
        caseFileList = [file for file in os.listdir(casePath) if file.endswith(".xlsx")]
    else:
        caseFileList = [caseFileName]
    return caseFileList


def get_run_case_list(parseExcel: ParseExcel):
    """
    获取被测试用例列表
    :param parseExcel:
    :return:
    """
    runCaseList = []
    # 默认第一个表格为测试用例表格，获取用例表格中索要执行的测试用例集合
    caseSheetName = parseExcel.get_sheet_name()[0]
    caseCountNum = parseExcel.get_real_row_count(caseSheetName)
    # 判断不执行的用例
    for caseRow in range(2, caseCountNum + 1):
        isRun = parseExcel.get_cell_data(caseSheetName, caseRow, Variable.IsRun)
        if isRun.lower() == "y":
            runCaseList.append(parseExcel.get_cell_data(caseSheetName, caseRow, Variable.CaseId))
        else:
            result_statistics(notRun=1)
    return runCaseList


def execute_step(parseExcel: ParseExcel, stepSheet: str, threadNum: int):
    """
    遍历步骤表执行测试用例
    :param parseExcel: 实例化解析类对象
    :param stepSheet: 表明
    :return:
    """
    global driver, log

    caseRunPass, logList = True, []
    # 获取步骤表中测试数据总行数
    stepRowCount = parseExcel.get_real_row_count(stepSheet)
    for row in range(2, stepRowCount + 1):
        rowData = parseExcel.get_row_data(stepSheet, row)
        try:
            # 每行数据中的关键字反射函数方法执行测试
            driver = key_word_map_api(rowData, threadNum)
        except:
            screenShotPath = Base(driver).screen_shot()
            errorInfo = traceback.format_exc()
            parseExcel.write_step_error_all_info(stepSheet, row, parseExcel.Fail, errorInfo, screenShotPath)
            log = f"--- [步骤]-编号：{rowData[0]}, - 步骤描述：{rowData[1]}, - 关键字：{rowData[2]}, -> 测试失败！！！" \
                  f"\n错误截图：{screenShotPath}，\n失败原因：\n{errorInfo}"
            Log.error(log)
            logList.append(log)
            caseRunPass = False
            Base(driver).quite()  # 退出浏览器避免消耗资源
            break
        else:
            parseExcel.write_step_result(stepSheet, row, parseExcel.Pass)
            parseExcel.clear_step_error_info(stepSheet, row)
            log = f"--- [步骤]-编号：{rowData[0]}, - 步骤描述：{rowData[1]}, - 关键字：{rowData[2]}, -> 测试通过"
            Log.info(log)
            logList.append(log)
        finally:
            parseExcel.write_step_end_time(stepSheet, row)
    # 返回一个用例所有步骤执行测试结果
    return caseRunPass, logList


def execute_case(parseExcel: ParseExcel, caseId, threadNum):
    """
    执行一个用例脚本
    :return:
    """
    caseSheet = parseExcel.get_sheet_name()[0]
    caseRow = parseExcel.get_case_id_row(caseSheet, caseId)
    caseName = parseExcel.get_cell_data(caseSheet, caseRow, Variable.CaseName)
    Log.info(f"-【用例】开始执行测试：{caseId}, - 用例名称：{caseName}")
    caseRunRes, logList = execute_step(parseExcel, caseId, threadNum)
    parseExcel.write_case_end_time(caseSheet, caseRow)
    # 写入用例测试结果
    if caseRunRes:
        result_statistics(passCount=1, passInfo={caseId: "\n".join(logList)})
        parseExcel.write_case_result(caseSheet, caseRow, parseExcel.Pass)
    else:
        result_statistics(failCount=1, errorInfo={caseId: "\n".join(logList)})
        parseExcel.write_case_result(caseSheet, caseRow, parseExcel.Fail)


def execute_case_by_thread(parseExcel, threadNum):
    """
    多线程执行测试用例
    :param parseExcel:
    :param threadNum: 线程数量
    :return:
    """
    runCaseList = get_run_case_list(parseExcel)

    # 根据线启动程数每次从用例列表中取对应数量的值列表
    startIndex, endIndex = 0, threadNum
    while True:
        threadCaseLs = runCaseList[startIndex:endIndex]
        startIndex += threadNum
        endIndex += threadNum
        if threadCaseLs == []:
            break
        run_by_thread(parseExcel, threadCaseLs, threadNum, funcName=execute_case)


def execute_all_case(threadNum, caseFileName=None):
    """
    遍历所有用例文件中的所有用例及步骤开始执行返回测试结果数据
    :param caseFileName:
    :return:
    """
    caseFileLs = get_run_case_file_list(caseFileName)
    for caseFile in caseFileLs:
        parseExcel = ParseExcel(casePath + caseFile)
        execute_case_by_thread(parseExcel, threadNum)
